//
//
//


#include <iostream>
#include <math.h>

using namespace std;

//定义时间格式
struct Datetype
{
    int year;
    int month;
    int day;
    //int hour;
    //int minute;
    //int second;
};

//控制参数: 最大迭代次数max_num、收敛精度accuracy、打印标志flag_print、人为设置的初值init_val、控制参数默认标志flag_default
struct ControlParameter
{
    int max_num;
    double accuracy;
    char flag_print;
    double init_val;
    bool flag_default;
};


template<class T >
class CalculateSqrt
{
    public:
    CalculateSqrt();
    virtual ~CalculateSqrt();
    double Solve(const T init_val );                //求平方根函数.init_val的平方根
    void SetParameter();                            //设置控制参数函数，调用后可对控制参数contrl_para进行设置

    private:
    int m_inter_num;                                //求平方根时的迭代次数
    struct ControlParameter contrl_para;            //控制参数
};

template<class T >
CalculateSqrt<T >::CalculateSqrt()
{
    m_inter_num = 0;
    contrl_para.max_num = 50;
    contrl_para.accuracy = 1e-5;
    contrl_para.flag_print = 'Y';
    contrl_para.flag_default = true;
}

template<class T >
CalculateSqrt<T >::~CalculateSqrt()
{
}

//计算平方根并输出
template<class T >
double CalculateSqrt<T >::Solve (const T init_val )
{
    cout << "==========calculate the square root......==========" << endl;
    double a = init_val;
    double x0 , x1 ;


    if (!contrl_para.flag_default)
        x1 = contrl_para.init_val;
    else
        x1 = a;

//迭代计算平方根
    m_inter_num = 0;
    do
    {
        x0 = x1;
        x1 = (x0 + a / x0) / 2;
        m_inter_num++;
        if(contrl_para.flag_print =='Y' || contrl_para.flag_print == 'y')
        {
            cout << "m_inter_num = "<< m_inter_num << "\t\t" << "x0 = "<< x0 << "\t\t\t" << "x1 = " << x1 << endl;
        }
    }
    while (fabs(x1 - x0) >= contrl_para.accuracy && m_inter_num < contrl_para.max_num );

    cout << "the square root is:\t" << x1 << endl;
    cout << "==========calculate the square root end==========" << endl;
    return x1;
}


template<class T >
void CalculateSqrt<T >::SetParameter()
{
    cout << "Please enter the maximum iterations:";
    cin >> contrl_para.max_num;
    cout << "Please enter the accuracy:";
    cin >> contrl_para.accuracy;
    cout << "Please enter Y/y if you want to print the iterative procedure information?";
    cin >> contrl_para.flag_print;
    cout << "Please enter the manual init_val:";
    cin >> contrl_para.init_val;
    contrl_para.flag_default = false;

    cout << contrl_para.max_num << endl<<contrl_para.accuracy<<endl<<contrl_para.flag_print<<endl<< contrl_para.flag_default;
}

//
class CalculateSeconds
{
    public:
    double Time(Datetype date);                             //计算data到1970年1月1日的秒数
    double Difftime(Datetype date1, Datetype date2 );       //计算data2和data1之间相差的秒数
    void Getdate(Datetype* date);                           //输入日期函数
};

//
double CalculateSeconds::Time(Datetype date_temp)
{
    struct Datetype date = date_temp;
    int temp;
    double day_num = 0;

    for(temp = 1970; temp <= date.year; temp++ )
    {
        if((temp % 4 ==0 && temp % 100 != 0) || temp % 400 == 0 )
            day_num +=366;
        else
            day_num +=365;
    }

    switch(date.month)
    {
        case 1:
            day_num = day_num + date.day - 1;
            break;
        case 2:
            day_num = day_num + date.day + 30;
            break;
         case 3:
            day_num = day_num + date.day + 58;
            break;
        case 4:
            day_num = day_num + date.day + 89;
            break;
        case 5:
            day_num = day_num + date.day + 119;
            break;
        case 6:
            day_num = day_num + date.day + 150;
            break;
        case 7:
            day_num = day_num + date.day + 180;
            break;
        case 8:
            day_num = day_num + date.day + 211;
            break;
        case 9:
            day_num = day_num + date.day + 242;
            break;
        case 10:
            day_num = day_num + date.day + 272;
            break;
        case 11:
            day_num = day_num + date.day + 303;
            break;
        case 12:
            day_num = day_num + date.day + 333;
            break;
    }
    if(date.month > 3 &&((temp % 4 ==0 && temp % 100 != 0) || temp % 400 == 0  ))
        day_num++;

    return day_num * 86400;
}

double CalculateSeconds::Difftime(Datetype date1, Datetype date2 )
{
    cout << (Time(date2) - Time(date1)) << endl;
    return fabs((Time(date2) - Time(date1)));
}

void CalculateSeconds::Getdate(struct Datetype* date)
{
    while (1)
    {
        cout << "Please enter the year:";
        cin >> date->year;
        cout << "Please enter the month:";
        cin >> date->month;
        cout << "Please enter the day:";
        cin >> date->day;

        //判断输入的日期是否合法
        if (date->year >= 1970 && date->month >= 1 && date->month <= 12 && date->day >=1 && date->day <=31)
        {
            if (date->month == 1 || date->month == 3 || date->month == 5 || date->month == 7 || date->month == 8 || date->month == 10 || date->month == 12 )
                break;
            else
            {
                if (date->month != 2 && date->day !=31 )
                    break;
                else
                 {
                    if (date->month == 2 && date->day <= 28)
                        break;
                    else
                        if (date->day == 29 && ((date->year % 4 ==0 && date->year % 100 != 0) || date->year % 400 == 0 ))
                            break;
                        else
                            cout << "Error!The date is illegal!Plesase retry." << endl;
                }
            }
        }
        else
            cout << "Error!The date is illegal!Plesase retry." << endl;

    }
}


int main()
{
    static Datetype date1, date2;
    CalculateSqrt<double > calculatesqrt;
    CalculateSeconds calculateseconds;
    //void Getdate(struct Datetype date_temp);
    char change;
    double seconds;

//输入两个日期
    cout << "Please enter your birthday:" <<endl;
	calculateseconds.Getdate(&date1);
	cout << "Please enter the second date:" << endl;
	calculateseconds.Getdate(&date2);

    cout << date1.year << date1.month << date1.day << endl;
    cout << date2.year << date2.month << date2.day << endl;

//选择是否采用默认迭代控制参数,输入Y/y使用默认控制参数，否则另行输入设定
    cout << "Please enter Y/y if you want to change the control parameter.";
    cin >> change;
    if (change == 'Y' || change == 'y')
        calculatesqrt.SetParameter();

    seconds = calculateseconds.Difftime(date1, date2);
    cout << "seconds = " << seconds << endl;

//对秒数做开方运算，直到结果小于2为止
    for(int i = 1; seconds > 2; i++)
    {
        cout << endl<< i << endl;
        seconds = calculatesqrt.Solve(seconds);
    }

    return 0;
}
